package cn.juque.jdfsystem.threads;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.juque.common.base.PageInfo;
import cn.juque.common.constants.NumberConstant;
import cn.juque.common.constants.YesOrNoEnum;
import cn.juque.jdfsystem.cache.RegisterInfoCache;
import cn.juque.jdfsystem.entity.FileInfo;
import cn.juque.jdfsystem.entity.FileViewLogInfo;
import cn.juque.lucenecandy.core.base.BaseEntity;
import cn.juque.lucenecandy.core.base.DeleteByIdsWrapperBuilder;
import cn.juque.lucenecandy.core.base.IdsQueryWrapperBuilder;
import cn.juque.lucenecandy.core.base.QueryWrapperBuilder;
import cn.juque.lucenecandy.helper.IndexHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.SortField;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author juque
 * @version 1.0.0
 * <ul>
 *     <li>FileViewsThreadPool</li>
 * </ul>
 * @date 2023-12-15 15:29:47
 **/
@Slf4j
@Component("fileViewsThreadPool")
public class FileViewsThreadPool {

    private static final PageInfo PAGE_INFO = new PageInfo();

    private static final Integer PAGE_LIMIT = NumberConstant.ONE_HUNDRED * NumberConstant.ONE_HUNDRED;

    private static final ThreadFactory THREAD_FACTORY = ThreadUtil.newNamedThreadFactory("file-views-", true);

    private static final ScheduledExecutorService EXECUTOR =
            new ScheduledThreadPoolExecutor(1, THREAD_FACTORY, new ThreadPoolExecutor.DiscardPolicy());
    private static final QueryWrapperBuilder<FileViewLogInfo> QUERY_WRAPPER_BUILDER = new QueryWrapperBuilder<>(FileViewLogInfo.class);

    @Resource
    private RegisterInfoCache registerInfoCache;

    @Resource
    private IndexHelper indexHelper;

    public void init() {
        PAGE_INFO.setPage(1);
        PAGE_INFO.setLimit(PAGE_LIMIT);
        QUERY_WRAPPER_BUILDER
                .matchInt(FileViewLogInfo::getSyncFlag, YesOrNoEnum.NO.getCode(), BooleanClause.Occur.MUST)
                .pageInfo(PAGE_INFO).addSort(BaseEntity::getUpdateTime, SortField.Type.LONG, false);
        EXECUTOR.scheduleAtFixedRate(this::execute, 0, 5, TimeUnit.SECONDS);
    }

    private void execute() {
        try {
            // 只有自己的ip的hashcode是最小值，才可以执行
            if (!Boolean.TRUE.equals(this.registerInfoCache.checkMinHashCode())) {
                return;
            }
            List<FileViewLogInfo> list = this.indexHelper.searchByPage(QUERY_WRAPPER_BUILDER.build());
            while (CollUtil.isNotEmpty(list)) {
                Map<String, List<FileViewLogInfo>> map = list.stream()
                        .collect(Collectors.groupingBy(FileViewLogInfo::getFileId, Collectors.toList()));
                IdsQueryWrapperBuilder<FileInfo> idQueryWrapperBuilder =
                        new IdsQueryWrapperBuilder<>(FileInfo.class, CollUtil.newArrayList(map.keySet()));
                List<FileInfo> fileInfoList = this.indexHelper.searchByIds(idQueryWrapperBuilder.build());
                Map<String, FileInfo> fileInfoMap = fileInfoList.stream().collect(Collectors.toMap(FileInfo::getId, t -> t, (k1, k2) -> k2));
                map.forEach((k, vList) -> {
                    if (!fileInfoMap.containsKey(k)) {
                        return;
                    }
                    FileInfo fileInfo = fileInfoMap.get(k);
                    long count = vList.stream().mapToLong(FileViewLogInfo::getViewCount).sum();
                    long viewNum = Objects.isNull(fileInfo.getPageviewTimes()) ? 0 : fileInfo.getPageviewTimes();
                    fileInfo.setPageviewTimes(viewNum + count);
                    this.indexHelper.updateDocumentById(fileInfo);
                    List<String> vIdList = vList.stream().map(BaseEntity::getId).collect(Collectors.toList());
                    DeleteByIdsWrapperBuilder<FileViewLogInfo> deleteByIdsWrapperBuilder =
                            new DeleteByIdsWrapperBuilder<>(FileViewLogInfo.class, vIdList);
                    this.indexHelper.deleteByIds(deleteByIdsWrapperBuilder.build());
                });
                list = this.indexHelper.searchByPage(QUERY_WRAPPER_BUILDER.build());
            }
        } catch (Exception e) {
            log.error("同步文件浏览量异常", e);
        }
    }
}
